unit fGlsPluginMenu;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls,
  uConstants,
  uGlsVector,
  uGlsTree,
  uModelParameters;

type                  
  TGlsPluginMenuForm = class(TForm)
    PluginListBox: TListBox;
    Label2: TLabel;
    CopyrightLabel: TLabel;
    
    RenderButton: TButton;
    SettingsButton: TButton;
    Label1: TLabel;
    DescriptionLabel: TLabel;
    procedure FormActivate(Sender: TObject);
    procedure RenderButtonClick(Sender: TObject);
    procedure SettingsButtonClick(Sender: TObject);
    procedure PluginListBoxClick(Sender: TObject);
  private
    FTree: TTree;
    FModelParameters: TModelParameters;
     
  public
     
  end;

var GlsPluginMenuForm: TGlsPluginMenuForm;

//==========================================================================
implementation

uses
  fGlsProgress,
  fGlsTree;

var   GlsDLLDescriptionList,GlsDLLCopyrightList,GlsDLLList: TStringList;

type TDLLFunction = function: integer; stdcall;
     TInitialize = function(MaxX, MaxY, MaxZ: real; TotalStems: integer): integer; stdcall;
     TAddStem = function(Sections: TList): integer; stdcall;
     TAddLeaf = function(Points: TList; LeafColor: integer; LeafColorVariation: boolean): integer; stdcall;
     TAddFruit = function(Points: TList; FruitfColor: integer; FruitColorVariation: boolean): integer; stdcall;
{$R *.dfm}

procedure TGlsPluginMenuForm.FormActivate(Sender: TObject);
var ASearchRec: TSearchRec;
    DLLInstance: THandle;
    DLLName: string;
    DLLCopyright: string;
    DLLDescription: string;
begin
  PluginListBox.Clear;
  GlsDLLList.Clear;
  GlsDLLDescriptionList.Clear;
  GlsDLLCopyrightList.Clear;                   {\plugins\}
  if FindFirst(ExtractFilePath(ParamStr(0)) + '*.dll', faArchive, ASearchRec) = 0 then
  begin
    repeat
      GlsDLLList.Add(ExtractFilePath(ParamStr(0)) {+ '\plugins\'} + ASearchRec.Name);
      DLLInstance := LoadLibrary(PChar(ExtractFilePath(ParamStr(0)) {+ '\plugins\'} + ASearchRec.Name));
      if DLLInstance = 0 then MessageDlg('Error loading the DLL ' + ASearchRec.Name, mtError, [mbOK], 0)
      else
      begin
        SetLength(DLLName, 100);
        SetLength(DLLCopyright, 100);
        SetLength(DLLDescription, 100);
        LoadString(DLLInstance, IDS_PLUGINNAME, PChar(DLLName), Length(DLLName));
        LoadString(DLLInstance, IDS_COPYRIGHT, PChar(DLLCopyright), Length(DLLCopyright));
        LoadString(DLLInstance, IDS_DESCRIPTION, PChar(DLLDescription), Length(DLLDescription));
        If Pos('TReal',DLLDescription)>0 then
        begin
        PluginListBox.Items.Add(trim(DLLName));
        CopyrightLabel.Caption := trim(DLLCopyright);
        GlsDLLCopyrightList.Add(trim(DLLCopyright));
        DescriptionLabel.Caption := trim(DLLDescription);
        GlsDLLDescriptionList.Add(trim(DLLDescription));
        end else
        GlsDLLList.Delete(GlsDLLList.Count-1);
      end;
      FreeLibrary(DLLInstance);
    until FindNext(ASearchRec) <> 0;
    FindClose(ASearchRec);
    If GlsDLLList.Count>0 then PluginListBox.ItemIndex := 0;
        SetLength(DLLName, 0);
        SetLength(DLLCopyright, 0);
        SetLength(DLLDescription, 0);
  end
  else MessageDlg('No plugins available...', mtInformation, [mbOK], 0);
end;

procedure TGlsPluginMenuForm.RenderButtonClick(Sender: TObject);
var DLLInstance: THandle;
    Finalize: TDLLFunction;
    AddStem: TAddStem;
    AddLeaf: TAddLeaf;
    AddFruit: TAddFruit;
    Initialize: TInitialize;

  function ExportTreeMesh(AStem: TStem): integer;
  { Pre: AStem <> nil
    Ret: 0, ExportTreeMesh was not successful
         1, ExportTreeMesh was successful, the tree mesh was successfully
            processed by the selected plugin }
  var i: integer;
  begin
    with AStem do
    begin
      Application.ProcessMessages;
      if AddStem(Sections) = 0 then
      begin
        Result := 0;
        Exit;
      end;
      Result := 1;
      for i := 0 to SubStems.Count - 1 do
      begin
        if ExportTreeMesh(TStem(SubStems[i])) = 0 then
        begin
          Result := 0;
          Exit;
        end;
        Result := 1;
      end;

      for i := 0 to Leafs.Count - 1 do
      begin
        if AddLeaf(Leafs[i], FModelParameters.LeafColor, FModelParameters.LeafColorVariation) = 0 then
        begin
          Result := 0;
          Exit;
        end;
        Result := 1;
      end;
      for i := 0 to Fruit.Count - 1 do
      begin
        if AddFruit(Fruit[i], FModelParameters.FruitColor, FModelParameters.FruitColorVariation) = 0 then
        begin
          Result := 0;
          Exit;
        end;
        Result := 1;
      end;
    end;
  end;

begin

  { Initialize the model parameters class }

  with aGlsTreeForm do
  begin
    LevelsNumberEditExit(nil);
    { The last level of recursion is reserved for leaves, so we only create
      LevelsNumberEdit.GetValue - 1 stem parameter levels. }
    FModelParameters := TModelParameters.Create(GlobalLevelsNumber);
    if GlobalLevelsNumber= 0 then
    begin
      MessageDlg('Levels should be a value greater than zero!', mtError, [mbOK], 0);
      Exit;
    end;
    InitModelParameters(FModelParameters);
    {FModelParameters.Levels :=GlobalLevelsNumber;}
    { Initialize the random number generator }
    if RandomTreeSeedNumber = 0 then Randomize
    else RandSeed := RandomTreeSeedNumber;
  end;

  { Show a progress form indicating that the tree is being generated }

  GlsUserCancelled := False;
  GlsProgressForm.Show;
  GlsProgressForm.Cursor := crHourGlass;
  GlsProgressForm.Update;

  { Create the entire tree structure }

  FTree := TTree.Create(FModelParameters, aGlsTreeForm.SeasonComboBox.ItemIndex);
  FTree.Trunk.CreateStructure(nil, FTree.TrunkLength, 0, 0);

  GlsProgressForm.ProgressBar.Max := FTree.TotalStems
                                     + FTree.TotalFruit
                                     + FTree.TotalGrownLeaves
                                     + TreeAddedLeavesTotal - 1;
  GlsProgressForm.ProgressBar.Position := 0;

  { And create the tree mesh points }

  FTree.Grow;

  { Close the progress form }

  GlsProgressForm.Close;


  { Use the DLL to export the tree structure to a 3d format }

  if not GlsUserCancelled then
  begin

    DLLInstance := 0;

    try
      DLLInstance := LoadLibrary(PChar(GlsDLLList[PluginListBox.ItemIndex]));
      if DLLInstance = 0 then MessageDlg('Error loading the DLL ' + PChar(GlsDLLList[PluginListBox.ItemIndex]), mtError, [mbOK], 0)
      else
      begin

        { Get the procedure addresses from the DLL }

        @Initialize := GetProcAddress(DLLInstance, 'Initialize');
        @Finalize := GetProcAddress(DLLInstance, 'Finalize');

        @AddStem := GetProcAddress(DLLInstance, 'AddStem');

        @AddLeaf := GetProcAddress(DLLInstance, 'AddLeaf');
        @AddFruit := GetProcAddress(DLLInstance, 'AddFruit');
        { Call the initialization section of the DLL }
        if Initialize(FTree.MaxX, FTree.MaxY, FTree.MaxZ, FTree.TotalStems) = 0 then Exit
        else
        begin

          { Export the mesh structure to the DLL }

          if ExportTreeMesh(FTree.Trunk) = 0 then
          begin
            MessageDlg('Error writing tree mesh to POV-Ray input file!', mtError, [mbOK], 0);
            Exit;
          end;

        end;

        { Free the memory occupied by the internal representation of the tree }

        FTree.Destroy;

        { Call the finalization section of the DLL }

        @Finalize := GetProcAddress(DLLInstance, 'Finalize');
        if Finalize = 0 then MessageDlg('Error finalizing the DLL ' + PChar(GlsDLLList[PluginListBox.ItemHeight]), mtError, [mbOK], 0);
      end;
    finally
      FreeLibrary(DLLInstance);
    end;
  end;
end;

procedure TGlsPluginMenuForm.SettingsButtonClick(Sender: TObject);
var DLLInstance: THandle;
    ShowForm: TDLLFunction;
begin
  DLLInstance := LoadLibrary(PChar(GlsDLLList[PluginListBox.ItemIndex]));
  if DLLInstance = 0 then
  MessageDlg('Error loading the DLL ' + PChar(GlsDLLList[PluginListBox.ItemIndex]),
   mtError, [mbOK], 0)
  else
  begin
    @ShowForm := GetProcAddress(DLLInstance, 'ShowForm');
    ShowForm;
  end;
  FreeLibrary(DLLInstance);
end;

procedure TGlsPluginMenuForm.PluginListBoxClick(Sender: TObject);
var  i: Integer;
begin
  for i := 0 to (PluginListBox.Items.Count - 1) do
  begin
    try
      if PluginListBox.Selected[i] then
      begin
        CopyrightLabel.Caption := GlsDLLCopyrightList[i];
        DescriptionLabel.Caption := GlsDLLDescriptionList[i];
      end
     finally
     { do something here }
     end;
  end;
end;



initialization

GlsDLLList := TStringList.Create;
GlsDLLDescriptionList:= TStringList.Create;
GlsDLLCopyrightList:= TStringList.Create;

finalization

GlsDLLList.Free;
GlsDLLDescriptionList.Free;
GlsDLLCopyrightList.Free;

end.
